package cn.iocoder.yudao.module.system.service.gugu;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.gugu.gugu.*;
import cn.iocoder.yudao.module.system.dal.dataobject.college.CollegeDO;
import cn.iocoder.yudao.module.system.dal.dataobject.collegeenrollmentplan.CollegeEnrollmentPlanDO;
import cn.iocoder.yudao.module.system.dal.mysql.collegeenrollmentplan.CollegeEnrollmentPlanMapper;
import cn.iocoder.yudao.module.system.service.college.CollegeService;
import cn.iocoder.yudao.module.system.util.gugu.GuGuDataUtils;
import cn.iocoder.yudao.module.system.util.gugu.MajorNameBracketProcessor;
import cn.iocoder.yudao.module.system.util.SubjectSelectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 高校招生计划服务实现类
 */
@Service
@Slf4j
public class CollegeEnrollmentPlanServiceImpl implements CollegeEnrollmentPlanService {

    @Resource
    private CollegeEnrollmentPlanMapper collegeEnrollmentPlanMapper;

    @Resource
    private CollegeService collegeService;

    // 中国省份列表
    private static final List<String> CHINA_PROVINCES = Arrays.asList(
            "北京", "天津", "河北", "山西", "内蒙古", "辽宁", "吉林", "黑龙江",
            "上海", "江苏", "浙江", "安徽", "福建", "江西", "山东", "河南",
            "湖北", "湖南", "广东", "广西", "海南", "重庆", "四川", "贵州",
            "云南", "西藏", "陕西", "甘肃", "青海", "宁夏", "新疆"
    );

    // 数据获取线程池
    private final ExecutorService dataFetchExecutor = Executors.newFixedThreadPool(3);

    // 数据保存线程池
    private final ExecutorService dataSaveExecutor = Executors.newFixedThreadPool(2);

    // 请求频率控制
    private volatile long lastRequestTime = 0;
    private static final long MIN_REQUEST_INTERVAL = 1000; // 最小请求间隔1秒

    @Override
    @Cacheable(value = "enrollmentPlanInfo#1d",
               key = "#reqVO.schoolName + ':' + #reqVO.collegeMajorName + ':' + #reqVO.provinceName + ':' + #reqVO.type + ':' + #reqVO.year + ':' + #reqVO.pageIndex + ':' + #reqVO.pageSize + ':' + #reqVO.specialGroup + ':' + #reqVO.specialCode + ':' + #reqVO.specialGroupName",
               unless = "#result == null or #result.get('success') != true")
    public Map<String, Object> getCollegeEnrollmentPlanInfo(CollegeEnrollmentPlanQueryReqVO reqVO) {
        log.debug("查询招生计划数据: 学校={}, 专业={}, 省份={}, 类型={}, 年份={}",
                 reqVO.getSchoolName(), reqVO.getCollegeMajorName(), reqVO.getProvinceName(),
                 reqVO.getType(), reqVO.getYear());

        // 添加防护措施，避免递归调用
        try {
            // 添加数据量检查，防止处理过大的数据集
            if (reqVO.getPageSize() != null && reqVO.getPageSize() > 1000) {
                log.warn("请求的页面大小过大: {}, 限制为1000", reqVO.getPageSize());
                reqVO.setPageSize(1000);
            }

            return GuGuDataUtils.getCollegeEnrollmentPlanInfo(reqVO);
        } catch (StackOverflowError e) {
            log.error("查询招生计划数据时发生StackOverflowError: 学校={}, 专业={}, 省份={}, 类型={}, 年份={}",
                     reqVO.getSchoolName(), reqVO.getCollegeMajorName(), reqVO.getProvinceName(),
                     reqVO.getType(), reqVO.getYear(), e);

            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "数据量过大，请缩小查询范围或联系管理员");
            return errorResult;
        } catch (Exception e) {
            log.error("查询招生计划数据失败: 学校={}, 专业={}, 省份={}, 类型={}, 年份={}, 错误: {}",
                     reqVO.getSchoolName(), reqVO.getCollegeMajorName(), reqVO.getProvinceName(),
                     reqVO.getType(), reqVO.getYear(), e.getMessage(), e);

            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "查询失败: " + e.getMessage());
            return errorResult;
        }
    }

    @Override
    // @Cacheable(value = "enrollmentPlanMajor#1d",
    //            key = "#schoolName + ':' + #majorName + ':' + #provinceName + ':' + #typeName + ':' + #year + ':filtered_v2'",
    //            unless = "#result == null or #result.isEmpty()")
    public List<CollegeEnrollmentPlanInfo> getEnrollmentPlanForMajor(String schoolName, String majorName,
                                                                     String provinceName, String typeName, Integer year) {
        log.debug("从数据库查询专业招生计划数据: 学校={}, 专业={}, 省份={}, 类型={}, 年份={}",
                 schoolName, majorName, provinceName, typeName, year);

        try {
            // 处理不同年份的typeName转换
            String actualTypeName = determineTypeNameForYear(provinceName, typeName, year);
            if (actualTypeName != null && !actualTypeName.equals(typeName)) {
                log.debug("根据年份{}转换typeName: {} -> {}", year, typeName, actualTypeName);
            }

            // 从数据库查询招生计划数据，使用支持括号匹配和typeName过滤的方法
            List<CollegeEnrollmentPlanDO> planDOList;

            if (schoolName != null && majorName != null) {
                // 扩展专业名称列表，包含原始名称和括号内的专业名称
                List<String> expandedMajorNames = expandMajorNamesWithBracketContent(Arrays.asList(majorName));
                List<String> schoolNames = Arrays.asList(schoolName);

                log.debug("扩展后的专业名称: {}", expandedMajorNames);

                // 使用支持括号处理、专业组智能匹配和typeName过滤的查询方法
                // 从专业名称中提取专业组信息用于智能匹配
                String subjectGroupForMatching = extractSubjectGroupFromMajorName(majorName);
                planDOList = collegeEnrollmentPlanMapper.selectExistingEnrollmentPlansWithBracketHandlingAndType(
                        schoolNames, expandedMajorNames, provinceName, year, actualTypeName, subjectGroupForMatching);
                
                log.debug("专业组智能匹配: 专业={}, 提取的专业组={}", majorName, subjectGroupForMatching);
            } else {
                // 如果学校名称或专业名称为空，使用原有的查询方法但加入typeName过滤
                planDOList = collegeEnrollmentPlanMapper.selectListBySchoolAndMajorWithType(
                        schoolName, majorName, provinceName, year, actualTypeName);
            }

            if (planDOList == null || planDOList.isEmpty()) {
                log.debug("未找到招生计划数据: 学校={}, 专业={}, 省份={}, 年份={}, 类型={}",
                         schoolName, majorName, provinceName, year, actualTypeName);
                return new ArrayList<>();
            }

            // 转换为CollegeEnrollmentPlanInfo格式
            List<CollegeEnrollmentPlanInfo> enrollmentPlanInfoList = planDOList.stream()
                    .map(this::convertToCollegeEnrollmentPlanInfo)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            // 过滤掉国家专项计划和提前批数据
            List<CollegeEnrollmentPlanInfo> filteredList = enrollmentPlanInfoList.stream()
                    .filter(plan -> {
                        String batchName = plan.getBatchName();
                        if (batchName == null || batchName.trim().isEmpty()) {
                            return true; // 保留没有批次信息的招生计划
                        }
                        // 过滤掉包含"国家专项"或"提前批"的招生计划
                        return !batchName.contains("国家专项") && !batchName.contains("提前批");
                    })
                    .collect(Collectors.toList());

            log.debug("从数据库查询到{}条招生计划数据，过滤后剩余{}条", enrollmentPlanInfoList.size(), filteredList.size());
            return filteredList;

        } catch (Exception e) {
            log.error("从数据库查询招生计划数据失败: 学校={}, 专业={}, 省份={}, 年份={}, 错误: {}",
                     schoolName, majorName, provinceName, year, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    @Override
    public List<CollegeEnrollmentPlanInfo> getEnrollmentPlanForMajorWithSubjectGroup(String schoolName, String majorName,
                                                                     String provinceName, String typeName, Integer year, String subjectGroup) {
        log.debug("从数据库查询专业招生计划数据（支持专业组匹配）: 学校={}, 专业={}, 省份={}, 类型={}, 年份={}, 专业组={}",
                 schoolName, majorName, provinceName, typeName, year, subjectGroup);

        try {
            // 处理不同年份的typeName转换
            String actualTypeName = determineTypeNameForYear(provinceName, typeName, year);
            if (actualTypeName != null && !actualTypeName.equals(typeName)) {
                log.debug("根据年份{}转换typeName: {} -> {}", year, typeName, actualTypeName);
            }

            // 从数据库查询招生计划数据，使用支持括号匹配、专业组智能匹配和typeName过滤的方法
            List<CollegeEnrollmentPlanDO> planDOList;

            if (schoolName != null && majorName != null) {
                // 扩展专业名称列表，包含原始名称和括号内的专业名称
                List<String> expandedMajorNames = expandMajorNamesWithBracketContent(Arrays.asList(majorName));
                List<String> schoolNames = Arrays.asList(schoolName);

                log.debug("扩展后的专业名称: {}", expandedMajorNames);

                // 使用支持括号处理、专业组智能匹配和typeName过滤的查询方法
                // 如果没有传入专业组信息，从专业名称中提取
                String subjectGroupForMatching = subjectGroup;
                if (subjectGroupForMatching == null || subjectGroupForMatching.trim().isEmpty()) {
                    subjectGroupForMatching = extractSubjectGroupFromMajorName(majorName);
                }
                
                planDOList = collegeEnrollmentPlanMapper.selectExistingEnrollmentPlansWithBracketHandlingAndType(
                        schoolNames, expandedMajorNames, provinceName, year, actualTypeName, subjectGroupForMatching);
                
                log.debug("专业组智能匹配: 专业={}, 传入专业组={}, 最终使用专业组={}", majorName, subjectGroup, subjectGroupForMatching);
            } else {
                // 如果学校名称或专业名称为空，使用原有的查询方法但加入typeName过滤
                planDOList = collegeEnrollmentPlanMapper.selectListBySchoolAndMajorWithType(
                        schoolName, majorName, provinceName, year, actualTypeName);
            }

            if (planDOList == null || planDOList.isEmpty()) {
                log.debug("未找到招生计划数据: 学校={}, 专业={}, 省份={}, 年份={}, 类型={}, 专业组={}",
                         schoolName, majorName, provinceName, year, actualTypeName, subjectGroup);
                return new ArrayList<>();
            }

            // 转换为CollegeEnrollmentPlanInfo格式
            List<CollegeEnrollmentPlanInfo> enrollmentPlanInfoList = planDOList.stream()
                    .map(this::convertToCollegeEnrollmentPlanInfo)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            // 过滤掉国家专项计划和提前批数据
            List<CollegeEnrollmentPlanInfo> filteredList = enrollmentPlanInfoList.stream()
                    .filter(plan -> {
                        String batchName = plan.getBatchName();
                        if (batchName == null || batchName.trim().isEmpty()) {
                            return true; // 保留没有批次信息的招生计划
                        }
                        // 过滤掉包含"国家专项"或"提前批"的招生计划
                        return !batchName.contains("国家专项") && !batchName.contains("提前批");
                    })
                    .collect(Collectors.toList());

            log.debug("查询到招生计划数据: {} 条，过滤后: {} 条", enrollmentPlanInfoList.size(), filteredList.size());
            return filteredList;

        } catch (Exception e) {
            log.error("查询专业招生计划数据失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 根据省份、年份和typeName确定实际的typeName
     * 处理不同年份可能使用不同typeName的情况（如2024年用"物理类"，2022年用"理科"）
     *
     * @param provinceName 省份名称
     * @param typeName 原始typeName
     * @param year 年份
     * @return 实际应该使用的typeName
     */
    private String determineTypeNameForYear(String provinceName, String typeName, Integer year) {
        if (typeName == null || typeName.isEmpty() || provinceName == null || year == null) {
            return typeName;
        }

        try {
            // 根据typeName确定首选科目
            String firstSubject = null;
            if (typeName.contains("物理") || typeName.contains("理科")) {
                firstSubject = "物理";
            } else if (typeName.contains("历史") || typeName.contains("文科")) {
                firstSubject = "历史";
            }

            if (firstSubject != null) {
                // 使用SubjectSelectionUtils工具类根据省份、年份和首选科目获取对应的科目类型
                String actualTypeName = SubjectSelectionUtils.getSubjectSelectionType(
                        provinceName, String.valueOf(year), firstSubject);

                if (actualTypeName != null && !actualTypeName.isEmpty()) {
                    return actualTypeName;
                }
            }
        } catch (Exception e) {
            log.warn("确定年份{}的typeName时发生异常，使用原始typeName: {}", year, e.getMessage());
        }

        // 如果无法确定，返回原始typeName
        return typeName;
    }

    /**
     * 控制API请求频率，避免请求过快触发限流
     */
    private void controlRequestRate() {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - lastRequestTime;

        if (lastRequestTime > 0 && elapsedTime < MIN_REQUEST_INTERVAL) {
            try {
                long sleepTime = MIN_REQUEST_INTERVAL - elapsedTime;
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.warn("请求频率控制被中断: {}", e.getMessage());
            }
        }

        lastRequestTime = System.currentTimeMillis();
    }

    /**
     * 获取指定省份和年份的所有招生计划数据
     * @param provinceName 省份名称
     * @param year 年份
     * @return 所有数据
     */
    private Map<String, Object> getEnrollmentPlanInfoAll(String provinceName, Integer year) {
        Map<String, Object> result = new HashMap<>();
        List<CollegeEnrollmentPlanInfo> allEnrollmentPlanList = new ArrayList<>();

        try {
            // 构建查询参数
            CollegeEnrollmentPlanQueryReqVO reqVO = new CollegeEnrollmentPlanQueryReqVO();
            reqVO.setPageIndex(1);
            reqVO.setPageSize(100); // 使用API允许的最大页面大小
            reqVO.setProvinceName(provinceName);
            reqVO.setYear(year);

            // 控制请求频率
            controlRequestRate();

            // 获取第一页数据，用于获取总数量和总页数
            Map<String, Object> firstPageResult = GuGuDataUtils.getCollegeEnrollmentPlanInfo(reqVO);

            if (!Boolean.TRUE.equals(firstPageResult.get("success"))) {
                return firstPageResult; // 如果第一页查询失败，直接返回错误
            }

            // 获取总数量和总页数
            int totalCount = (Integer) firstPageResult.get("totalCount");
            int totalPages = (Integer) firstPageResult.get("totalPages");

            log.info("查询到{}省{}年的招生计划数据总数量为{}，总页数为{}",
                    provinceName, year, totalCount, totalPages);

            // 添加数据量检查，防止内存溢出
//            if (totalCount > 50000) {
//                log.warn("{}省{}年数据量过大({})，可能导致内存问题，建议分批处理",
//                        provinceName, year, totalCount);
//                result.put("success", false);
//                result.put("message", String.format("数据量过大(%d条)，请联系管理员处理", totalCount));
//                return result;
//            }

            // 添加第一页的数据
            @SuppressWarnings("unchecked")
            List<CollegeEnrollmentPlanInfo> firstPageList =
                (List<CollegeEnrollmentPlanInfo>) firstPageResult.get("enrollmentPlanList");
            if (firstPageList != null && !firstPageList.isEmpty()) {
                allEnrollmentPlanList.addAll(firstPageList);
                log.info("成功获取第1页数据，共{}条记录", firstPageList.size());

                // 异步保存数据到数据库
                asyncSaveEnrollmentPlanData(new ArrayList<>(firstPageList));
            }

            // 如果有多页，使用多线程获取其他页的数据
            if (totalPages > 1) {
                // 限制最大页数，防止内存溢出
                int maxPages = Math.min(totalPages, 5000); // 最多处理500页
                if (totalPages > maxPages) {
                    log.warn("{}省{}年总页数({})超过限制，只处理前{}页",
                            provinceName, year, totalPages, maxPages);
                }

                // 创建一个线程安全的集合来存储所有页的数据
                final Map<Integer, List<CollegeEnrollmentPlanInfo>> pageDataMap = new ConcurrentHashMap<>();

                // 创建任务列表
                List<CompletableFuture<Void>> futures = new ArrayList<>();

                // 从第2页开始获取数据
                for (int pageIndex = 2; pageIndex <= maxPages; pageIndex++) {
                    final int currentPageIndex = pageIndex;

                    // 创建并提交任务
                    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                        try {
                            // 创建当前页的请求参数
                            CollegeEnrollmentPlanQueryReqVO pageReqVO = new CollegeEnrollmentPlanQueryReqVO();
                            pageReqVO.setPageIndex(currentPageIndex);
                            pageReqVO.setPageSize(100);
                            pageReqVO.setProvinceName(provinceName);
                            pageReqVO.setYear(year);

                            // 控制请求频率
                            controlRequestRate();

                            // 获取当前页数据
                            Map<String, Object> pageResult = GuGuDataUtils.getCollegeEnrollmentPlanInfo(pageReqVO);

                            if (Boolean.TRUE.equals(pageResult.get("success"))) {
                                @SuppressWarnings("unchecked")
                                List<CollegeEnrollmentPlanInfo> pageEnrollmentPlanList =
                                    (List<CollegeEnrollmentPlanInfo>) pageResult.get("enrollmentPlanList");
                                if (pageEnrollmentPlanList != null && !pageEnrollmentPlanList.isEmpty()) {
                                    // 将数据存入线程安全的Map
                                    pageDataMap.put(currentPageIndex, pageEnrollmentPlanList);
                                    log.info("成功获取第{}页数据，共{}条记录--剩余{}页",
                                            currentPageIndex, pageEnrollmentPlanList.size(), maxPages - currentPageIndex);

                                    // 立即异步保存数据
                                    final List<CollegeEnrollmentPlanInfo> dataToSave = new ArrayList<>(pageEnrollmentPlanList);
                                    asyncSaveEnrollmentPlanData(dataToSave);
                                }
                            } else {
                                log.error("查询第{}页失败: {}", currentPageIndex, pageResult.get("message"));
                            }
                        } catch (Exception e) {
                            log.error("处理第{}页数据时发生异常", currentPageIndex, e);
                        }
                    }, dataFetchExecutor);

                    futures.add(future);
                }

                // 等待所有任务完成，设置超时时间防止无限等待
                CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
                try {
                    allFutures.get(10, TimeUnit.MINUTES); // 最多等待10分钟
                } catch (TimeoutException e) {
                    log.error("等待数据获取任务超时，部分数据可能未完成");
                    allFutures.cancel(true);
                }

                // 按页码顺序添加数据
                for (int pageIndex = 2; pageIndex <= maxPages; pageIndex++) {
                    List<CollegeEnrollmentPlanInfo> pageData = pageDataMap.get(pageIndex);
                    if (pageData != null) {
                        allEnrollmentPlanList.addAll(pageData);
                    }
                }
            }

            // 构建返回结果
            result.put("success", true);
            result.put("enrollmentPlanList", allEnrollmentPlanList);
            result.put("totalCount", totalCount);
            result.put("pageIndex", 1);
            result.put("pageSize", allEnrollmentPlanList.size());
            result.put("totalPages", totalPages);
            result.put("isAllData", true);

            return result;
        } catch (Exception e) {
            log.error("获取{}省{}年招生计划数据失败: {}", provinceName, year, e.getMessage(), e);
            result.put("success", false);
            result.put("message", "查询招生计划数据失败: " + e.getMessage());
            return result;
        }
    }

    /**
     * 异步保存招生计划数据
     * @param enrollmentPlanList 招生计划数据列表
     */
    private void asyncSaveEnrollmentPlanData(List<CollegeEnrollmentPlanInfo> enrollmentPlanList) {
        if (enrollmentPlanList == null || enrollmentPlanList.isEmpty()) {
            return;
        }

        try {
            // 检查线程池状态
            if (dataSaveExecutor.isShutdown() || dataSaveExecutor.isTerminated()) {
                log.warn("数据保存线程池已关闭，无法提交异步任务，将直接同步保存数据");
                int savedCount = saveEnrollmentPlanData(enrollmentPlanList);
                log.info("同步保存{}条招生计划数据到数据库", savedCount);
            } else {
                // 使用线程池提交任务
                dataSaveExecutor.submit(() -> {
                    try {
                        int savedCount = saveEnrollmentPlanData(enrollmentPlanList);
                        log.info("异步保存{}条招生计划数据到数据库", savedCount);
                    } catch (Exception e) {
                        log.error("异步保存招生计划数据到数据库失败: {}", e.getMessage(), e);
                    }
                });
            }
        } catch (Exception e) {
            log.error("提交异步保存任务失败，将尝试同步保存: {}", e.getMessage(), e);
            try {
                // 如果提交失败，则在当前线程中同步执行
                int savedCount = saveEnrollmentPlanData(enrollmentPlanList);
                log.info("同步保存{}条招生计划数据到数据库", savedCount);
            } catch (Exception ex) {
                log.error("同步保存数据失败: {}", ex.getMessage(), ex);
            }
        }
    }

    @Override
    public Map<String, Object> batchImportEnrollmentPlanData(List<Integer> years, boolean useMultiThread) {
        log.info("开始批量导入历年高校招生计划数据，年份: {}, 多线程: {}", years, useMultiThread);

        Map<String, Object> result = new HashMap<>();
        AtomicInteger totalImported = new AtomicInteger(0);
        AtomicInteger totalProvinces = new AtomicInteger(0);
        AtomicInteger processedProvinces = new AtomicInteger(0);

        long startTime = System.currentTimeMillis();

        try {
            for (Integer year : years) {
                log.info("开始导入{}年数据", year);
                int yearImported = 0;

                if (useMultiThread) {
                    // 使用多线程处理
                    int threadCount = Math.min(CHINA_PROVINCES.size(), 5); // 最多使用5个线程
                    ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

                    try {
                        List<CompletableFuture<Integer>> futures = new ArrayList<>();

                        for (String province : CHINA_PROVINCES) {
                            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                                try {
                                    log.info("开始获取{}年{}省的招生计划数据", year, province);
                                    Map<String, Object> provinceResult = getEnrollmentPlanInfoAll(province, year);

                                    if (Boolean.TRUE.equals(provinceResult.get("success"))) {
                                        @SuppressWarnings("unchecked")
                                        List<CollegeEnrollmentPlanInfo> allEnrollmentPlanList =
                                            (List<CollegeEnrollmentPlanInfo>) provinceResult.get("enrollmentPlanList");

                                        int imported = allEnrollmentPlanList != null ? allEnrollmentPlanList.size() : 0;
                                        processedProvinces.incrementAndGet();
                                        log.info("{}年{}省数据导入完成，导入{}条数据", year, province, imported);
                                        return imported;
                                    } else {
                                        String message = (String) provinceResult.get("message");
                                        log.error("{}年{}省数据导入失败: {}", year, province, message);
                                        return 0;
                                    }
                                } catch (Exception e) {
                                    log.error("{}年{}省数据导入失败: {}", year, province, e.getMessage(), e);
                                    return 0;
                                }
                            }, executorService);

                            futures.add(future);
                        }

                        // 等待所有任务完成
                        for (CompletableFuture<Integer> future : futures) {
                            yearImported += future.get();
                        }

                        totalProvinces.addAndGet(CHINA_PROVINCES.size());

                    } finally {
                        executorService.shutdown();
                    }
                } else {
                    // 单线程处理
                    for (String province : CHINA_PROVINCES) {
                        try {
                            log.info("开始获取{}年{}省的招生计划数据", year, province);
                            Map<String, Object> provinceResult = getEnrollmentPlanInfoAll(province, year);

                            if (Boolean.TRUE.equals(provinceResult.get("success"))) {
                                @SuppressWarnings("unchecked")
                                List<CollegeEnrollmentPlanInfo> allEnrollmentPlanList =
                                    (List<CollegeEnrollmentPlanInfo>) provinceResult.get("enrollmentPlanList");

                                int imported = allEnrollmentPlanList != null ? allEnrollmentPlanList.size() : 0;
                                yearImported += imported;
                                processedProvinces.incrementAndGet();
                                totalProvinces.incrementAndGet();
                                log.info("{}年{}省数据导入完成，导入{}条数据", year, province, imported);
                            } else {
                                String message = (String) provinceResult.get("message");
                                log.error("{}年{}省数据导入失败: {}", year, province, message);
                            }
                        } catch (Exception e) {
                            log.error("{}年{}省数据导入失败: {}", year, province, e.getMessage(), e);
                        }
                    }
                }

                totalImported.addAndGet(yearImported);
                log.info("{}年数据导入完成，共导入{}条数据", year, yearImported);
            }

            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            result.put("success", true);
            result.put("totalImported", totalImported.get());
            result.put("totalProvinces", totalProvinces.get());
            result.put("processedProvinces", processedProvinces.get());
            result.put("duration", duration);
            result.put("message", String.format("批量导入完成，共处理%d个省份，导入%d条数据，耗时%d毫秒",
                    processedProvinces.get(), totalImported.get(), duration));

            log.info("批量导入历年高校招生计划数据完成: {}", result.get("message"));

        } catch (Exception e) {
            log.error("批量导入历年高校招生计划数据失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "批量导入失败: " + e.getMessage());
            result.put("totalImported", totalImported.get());
            result.put("processedProvinces", processedProvinces.get());
        }

        return result;
    }

    @Override
    public int importEnrollmentPlanDataByProvince(String provinceName, Integer year) {
        log.debug("开始导入{}年{}省招生计划数据", year, provinceName);

        try {
            Map<String, Object> result = getEnrollmentPlanInfoAll(provinceName, year);

            if (Boolean.TRUE.equals(result.get("success"))) {
                @SuppressWarnings("unchecked")
                List<CollegeEnrollmentPlanInfo> allEnrollmentPlanList =
                    (List<CollegeEnrollmentPlanInfo>) result.get("enrollmentPlanList");

                int totalImported = allEnrollmentPlanList != null ? allEnrollmentPlanList.size() : 0;
                log.debug("{}年{}省招生计划数据导入完成，共导入{}条", year, provinceName, totalImported);
                return totalImported;
            } else {
                String message = (String) result.get("message");
                log.error("{}年{}省招生计划数据导入失败: {}", year, provinceName, message);
                return 0;
            }
        } catch (Exception e) {
            log.error("{}年{}省招生计划数据导入异常: {}", year, provinceName, e.getMessage(), e);
            return 0;
        }
    }

    /**
     * 保存招生计划数据到数据库
     * @param enrollmentPlanList 招生计划数据列表
     * @return 保存的数据条数
     */
    private int saveEnrollmentPlanData(List<CollegeEnrollmentPlanInfo> enrollmentPlanList) {
        if (enrollmentPlanList == null || enrollmentPlanList.isEmpty()) {
            return 0;
        }

        int savedCount = 0;

        // 分批保存数据，每批最多500条
        int batchSize = 500;
        for (int i = 0; i < enrollmentPlanList.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, enrollmentPlanList.size());
            List<CollegeEnrollmentPlanInfo> batch = enrollmentPlanList.subList(i, endIndex);

            // 批量保存到数据库
            for (CollegeEnrollmentPlanInfo info : batch) {
                try {
                    // 查询是否已存在相同数据
                    CollegeEnrollmentPlanDO existingPlan = collegeEnrollmentPlanMapper.selectByUniqueKey(
                            info.getProvinceName(),
                            info.getSchoolUuid(),
                            info.getCollegeMajorName(),
                            info.getYear(),
                            info.getType(),
                            info.getBatchName()
                    );

                    // 转换为DO对象
                    CollegeEnrollmentPlanDO planDO = convertToCollegeEnrollmentPlanDO(info);

                    if (existingPlan != null) {
                        // 如果存在则更新
                        planDO.setId(existingPlan.getId()); // 设置ID用于更新
                        collegeEnrollmentPlanMapper.updateById(planDO);
                        savedCount++;
                    } else {
                        // 如果不存在则插入
                        collegeEnrollmentPlanMapper.insert(planDO);
                        savedCount++;
                    }

                } catch (Exception e) {
                    // 记录详细错误信息但继续处理其他记录
                    log.warn("保存招生计划数据失败: 省份={}, 学校UUID={}, 专业={}, 年份={}, 类型={}, 批次={}, 错误: {}",
                            info.getProvinceName(), info.getSchoolUuid(), info.getCollegeMajorName(),
                            info.getYear(), info.getType(), info.getBatchName(), e.getMessage());

                    // 如果是重复键错误，尝试查询并更新
                    if (e.getMessage() != null && e.getMessage().contains("Duplicate entry")) {
                        try {
                            log.info("检测到重复键错误，尝试更新现有记录");
                            CollegeEnrollmentPlanDO existingPlan = collegeEnrollmentPlanMapper.selectByUniqueKey(
                                    info.getProvinceName(),
                                    info.getSchoolUuid(),
                                    info.getCollegeMajorName(),
                                    info.getYear(),
                                    info.getType(),
                                    info.getBatchName()
                            );
                            if (existingPlan != null) {
                                CollegeEnrollmentPlanDO planDO = convertToCollegeEnrollmentPlanDO(info);
                                planDO.setId(existingPlan.getId());
                                collegeEnrollmentPlanMapper.updateById(planDO);
                                savedCount++;
                                log.info("成功更新重复记录");
                            }
                        } catch (Exception updateEx) {
                            log.error("更新重复记录失败: {}", updateEx.getMessage());
                        }
                    }
                }
            }
        }

        return savedCount;
    }

    /**
     * 转换CollegeEnrollmentPlanInfo为CollegeEnrollmentPlanDO
     * @param info API返回的数据
     * @return 数据库实体对象
     */
    private CollegeEnrollmentPlanDO convertToCollegeEnrollmentPlanDO(CollegeEnrollmentPlanInfo info) {
        return CollegeEnrollmentPlanDO.builder()
                .provinceName(info.getProvinceName())
                .schoolUuid(info.getSchoolUuid())
                .schoolName(info.getSchoolName())
                .collegeMajorName(info.getCollegeMajorName())
                .collegeMajorCode(info.getCollegeMajorCode())
                .year(info.getYear())
                .enrollmentNumbers(info.getEnrollmentNumbers())
                .inSchoolYears(info.getInSchoolYears())
                .classOne(info.getClassOne())
                .classTwo(info.getClassTwo())
                .batchName(info.getBatchName())
                .type(info.getType())
                .courseSelectionRequirements(info.getCourseSelectionRequirements())
                .specialGroup(info.getSpecialGroup())
                .specialCode(info.getSpecialCode())
                .specialGroupName(info.getSpecialGroupName())
                .collegeMajorBracketContent(info.getCollegeMajorBracketContent())
                .build();
    }

    @Override
    public List<CollegeEnrollmentPlanDO> getEnrollmentPlanFromDatabase(String schoolName, String majorName,
                                                                      String provinceName, Integer year) {
        // 使用支持括号匹配的查询方法
        if (schoolName != null && majorName != null) {
            // 扩展专业名称列表，包含原始名称和括号内的专业名称
            List<String> expandedMajorNames = expandMajorNamesWithBracketContent(Arrays.asList(majorName));
            List<String> schoolNames = Arrays.asList(schoolName);

            log.debug("getEnrollmentPlanFromDatabase - 扩展后的专业名称: {}", expandedMajorNames);

            // 使用支持括号处理的查询方法
            return collegeEnrollmentPlanMapper.selectExistingEnrollmentPlansWithBracketHandling(
                    schoolNames, expandedMajorNames, provinceName, year);
        } else {
            // 如果学校名称或专业名称为空，使用原有的查询方法
            return collegeEnrollmentPlanMapper.selectListBySchoolAndMajor(schoolName, majorName, provinceName, year);
        }
    }

    @Override
    public List<CollegeEnrollmentPlanDO> batchCheckEnrollmentPlansFromDatabase(List<String> schoolNames,
                                                                              List<String> majorNames,
                                                                              String provinceName, Integer year) {
        if (schoolNames == null || schoolNames.isEmpty() || majorNames == null || majorNames.isEmpty()) {
            return new ArrayList<>();
        }

        log.debug("批量查询招生计划数据: 学校数量={}, 专业数量={}, 省份={}, 年份={}",
                 schoolNames.size(), majorNames.size(), provinceName, year);

        // 扩展专业名称列表，包含原始名称和括号内的专业名称
        List<String> expandedMajorNames = expandMajorNamesWithBracketContent(majorNames);

        log.debug("扩展后的专业名称: {}", expandedMajorNames);

        return collegeEnrollmentPlanMapper.selectExistingEnrollmentPlansWithBracketHandling(
                schoolNames, expandedMajorNames, provinceName, year);
    }

    @Override
    public List<CollegeEnrollmentPlanDO> batchCheckEnrollmentPlansMultiYear(List<String> schoolNames,
                                                                           List<String> majorNames,
                                                                           String provinceName) {
        if (schoolNames == null || schoolNames.isEmpty() || majorNames == null || majorNames.isEmpty()) {
            return new ArrayList<>();
        }

        // 数据量检查，记录日志但不限制处理
        if (schoolNames.size() > 1000 || majorNames.size() > 1000) {
            log.info("处理大数据集，学校数量: {}, 专业数量: {}", schoolNames.size(), majorNames.size());
        }

        // 定义查询年份的优先级顺序
        List<Integer> years = Arrays.asList(2025, 2024, 2023, 2022);
        List<CollegeEnrollmentPlanDO> allExistingPlans = new ArrayList<>();
        Set<String> foundCombinationsWithYear = new HashSet<>(); // 改为包含年份的去重key

        log.info("开始多年份招生计划查询，学校数量: {}, 专业数量: {}, 省份: {}",
                schoolNames.size(), majorNames.size(), provinceName);

        try {
            // 扩展专业名称列表，包含原始名称和括号内的专业名称
            List<String> expandedMajorNames = expandMajorNamesWithBracketContent(majorNames);

            log.info("扩展后的专业名称数量: {}, 详情: {}", expandedMajorNames.size(), expandedMajorNames);

            // 先检查数据库中各年份的数据情况
//            checkYearlyDataAvailability(provinceName);

            for (Integer year : years) {
                log.info("开始查询{}年的招生计划数据", year);

                try {
                    // 查询当前年份的招生计划，使用支持括号处理的方法
                    List<CollegeEnrollmentPlanDO> yearPlans = collegeEnrollmentPlanMapper
                            .selectExistingEnrollmentPlansWithBracketHandling(schoolNames, expandedMajorNames, provinceName, year);

            log.info("{}年查询结果：找到{}个招生计划记录", year, yearPlans.size());

            if (!yearPlans.isEmpty()) {
                // 调试：打印前几条数据
                if (log.isDebugEnabled()) {
                    log.debug("{}年招生计划数据示例：", year);
                    for (int i = 0; i < Math.min(3, yearPlans.size()); i++) {
                        CollegeEnrollmentPlanDO plan = yearPlans.get(i);
                        log.debug("  - 学校: {}, 专业: {}, 年份: {}, 招生人数: {}",
                                plan.getSchoolName(), plan.getCollegeMajorName(), plan.getYear(), plan.getEnrollmentNumbers());
                    }
                }

                // 对于多年份查询，我们需要保留所有年份的数据
                // 只过滤完全相同的重复记录（相同年份、学校、专业、批次等）
                List<CollegeEnrollmentPlanDO> newPlans = new ArrayList<>();
                int duplicateCount = 0;

                // 高效优化：使用批量处理和优化的去重算法
                Map<String, CollegeEnrollmentPlanDO> uniquePlansMap = new LinkedHashMap<>();

                if (yearPlans.size() > 10000) {
                    // 大数据量时使用优化策略
                    log.info("{}年数据量较大({})，使用优化处理策略", year, yearPlans.size());

                    // 使用分批处理，每批处琅5000条记录
                    int batchSize = 5000;
                    for (int i = 0; i < yearPlans.size(); i += batchSize) {
                        int endIndex = Math.min(i + batchSize, yearPlans.size());
                        List<CollegeEnrollmentPlanDO> batch = yearPlans.subList(i, endIndex);

                        // 对每批数据进行去重处理
                        for (CollegeEnrollmentPlanDO plan : batch) {
                            String uniqueKey = buildUniqueKey(plan);
                            uniquePlansMap.putIfAbsent(uniqueKey, plan);
                        }

                        // 每处琅1万条记录输出一次进度
                        if ((i + batchSize) % 10000 == 0 || endIndex == yearPlans.size()) {
                            log.debug("{}年数据处理进度: {}/{}", year, endIndex, yearPlans.size());
                        }
                    }
                } else {
                    // 小数据量时使用传统方式
                    for (CollegeEnrollmentPlanDO plan : yearPlans) {
                        String uniqueKey = buildUniqueKey(plan);
                        uniquePlansMap.putIfAbsent(uniqueKey, plan);
                    }
                }

                // 过滤已存在于全局集合中的记录
                Iterator<Map.Entry<String, CollegeEnrollmentPlanDO>> iterator = uniquePlansMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, CollegeEnrollmentPlanDO> entry = iterator.next();
                    if (foundCombinationsWithYear.contains(entry.getKey())) {
                        duplicateCount++;
                        if (log.isDebugEnabled()) {
                            CollegeEnrollmentPlanDO plan = entry.getValue();
                            log.debug("{}年数据重复过滤：{} - {} (完全相同的记录)",
                                    year, plan.getSchoolName(), plan.getCollegeMajorName());
                        }
                        iterator.remove();
                    }
                }

                // 批量添加到全局去重集合和结果列表
                foundCombinationsWithYear.addAll(uniquePlansMap.keySet());
                newPlans.addAll(uniquePlansMap.values());

                // 计算当前批次内部的重复数量
                int batchDuplicates = yearPlans.size() - uniquePlansMap.size();

                    allExistingPlans.addAll(newPlans);
                    log.info("{}年处理完成：原始{}条，添加{}条，全局重复{}条，批次内重复{}条",
                            year, yearPlans.size(), newPlans.size(), duplicateCount, batchDuplicates);
                } else {
                    log.warn("{}年未找到任何招生计划数据", year);
                }
                } catch (Exception e) {
                    log.error("查询{}年招生计划数据失败: {}", year, e.getMessage(), e);
                    // 继续处理下一年的数据
                }
            }

            log.info("多年份查询完成，总共找到{}条招生计划记录（包含多年份数据）", allExistingPlans.size());

            // 统计各年份的数据量
            Map<Integer, Long> yearCounts = allExistingPlans.stream()
                    .collect(Collectors.groupingBy(CollegeEnrollmentPlanDO::getYear, Collectors.counting()));
            log.info("各年份数据分布：{}", yearCounts);

            // 按年份倒序排列，优先使用最新年份的数据
            allExistingPlans.sort((a, b) -> Integer.compare(b.getYear(), a.getYear()));

            return allExistingPlans;
        } catch (StackOverflowError e) {
            log.error("多年份招生计划查询发生StackOverflowError，返回空结果", e);
            return new ArrayList<>();
        } catch (Exception e) {
            log.error("多年份招生计划查询失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public Map<String, Object> getImportProgress() {
        Map<String, Object> progress = new HashMap<>();

        try {
            // 统计各年份的数据量
            Map<Integer, Long> yearCounts = new HashMap<>();
            for (int year = 2022; year <= 2024; year++) {
                Long count = collegeEnrollmentPlanMapper.countByYear(year);
                yearCounts.put(year, count);
            }

            // 统计各省份的数据量
            Map<String, Long> provinceCounts = new HashMap<>();
            for (String province : CHINA_PROVINCES) {
                Long count = collegeEnrollmentPlanMapper.countByProvince(province);
                provinceCounts.put(province, count);
            }

            progress.put("success", true);
            progress.put("yearCounts", yearCounts);
            progress.put("provinceCounts", provinceCounts);
            progress.put("totalProvinces", CHINA_PROVINCES.size());

        } catch (Exception e) {
            log.error("获取导入进度统计失败: {}", e.getMessage(), e);
            progress.put("success", false);
            progress.put("message", "获取进度统计失败: " + e.getMessage());
        }

        return progress;
    }

    @Override
    public CollegeEnrollmentPlanGroupRespVO getEnrollmentPlanGroupData(CollegeEnrollmentPlanGroupQueryReqVO reqVO) {
        log.info("开始分组查询招生计划数据，分组类型: {}, 页码: {}, 每页大小: {}",
                reqVO.getGroupType(), reqVO.getPageNo(), reqVO.getPageSize());

        CollegeEnrollmentPlanGroupRespVO respVO = new CollegeEnrollmentPlanGroupRespVO();
        respVO.setGroupType(reqVO.getGroupType());

        try {
            if ("school".equals(reqVO.getGroupType())) {
                // 按学校分组查询
                PageResult<SchoolGroupInfo> schoolGroups = getSchoolGroupData(reqVO);
                respVO.setSchoolGroups(schoolGroups);
            } else if ("major".equals(reqVO.getGroupType())) {
                // 按专业分组查询
                PageResult<MajorGroupInfo> majorGroups = getMajorGroupData(reqVO);
                respVO.setMajorGroups(majorGroups);
            } else {
                throw new IllegalArgumentException("不支持的分组类型: " + reqVO.getGroupType());
            }

            return respVO;
        } catch (Exception e) {
            log.error("分组查询招生计划数据失败: {}", e.getMessage(), e);
            throw new RuntimeException("分组查询失败: " + e.getMessage(), e);
        }
    }

    /**
     * 按学校分组查询数据
     */
    private PageResult<SchoolGroupInfo> getSchoolGroupData(CollegeEnrollmentPlanGroupQueryReqVO reqVO) {
        // 计算分页参数
        int offset = (reqVO.getPageNo() - 1) * reqVO.getPageSize();

        // 先查询总数
        Long total = collegeEnrollmentPlanMapper.countSchoolGroupStatistics(
                reqVO.getSchoolName(),
                reqVO.getCollegeMajorName(),
                reqVO.getProvinceName(),
                reqVO.getClassOne(),
                reqVO.getClassTwo(),
                reqVO.getBatchName(),
                reqVO.getType(),
                reqVO.getSchoolUuid(),
                reqVO.getYear()
        );

        // 查询分页数据
        List<Map<String, Object>> pageData = collegeEnrollmentPlanMapper.selectSchoolGroupStatistics(
                reqVO.getSchoolName(),
                reqVO.getCollegeMajorName(),
                reqVO.getProvinceName(),
                reqVO.getClassOne(),
                reqVO.getClassTwo(),
                reqVO.getBatchName(),
                reqVO.getType(),
                reqVO.getSchoolUuid(),
                reqVO.getYear(),
                offset,
                reqVO.getPageSize()
        );

        // 转换数据并关联学校基础信息
        List<SchoolGroupInfo> schoolGroups = convertToSchoolGroupInfoWithCollegeInfo(pageData);

        return new PageResult<>(schoolGroups, total);
    }

    /**
     * 按专业分组查询数据
     */
    private PageResult<MajorGroupInfo> getMajorGroupData(CollegeEnrollmentPlanGroupQueryReqVO reqVO) {
        // 查询更多数据用于合并（因为需要在Java层面合并相同专业名称）
        int largePageSize = Math.max(reqVO.getPageSize() * 10, 1000); // 查询更多数据

        // 查询数据
        List<Map<String, Object>> allData = collegeEnrollmentPlanMapper.selectMajorGroupStatistics(
                reqVO.getSchoolName(),
                reqVO.getCollegeMajorName(),
                reqVO.getProvinceName(),
                reqVO.getClassOne(),
                reqVO.getClassTwo(),
                reqVO.getBatchName(),
                reqVO.getType(),
                reqVO.getSchoolUuid(),
                reqVO.getYear(),
                0,
                largePageSize
        );

        // 在Java层面合并相同的专业名称（去除括号后）
        Map<String, MajorGroupInfo> mergedData = new LinkedHashMap<>();

        for (Map<String, Object> data : allData) {
            String rawMajorName = (String) data.get("majorName");
            String cleanMajorName = removeBracketsFromMajorName(rawMajorName);
            String classOne = (String) data.get("classOne");
            String classTwo = (String) data.get("classTwo");

            // 使用清理后的专业名称+专业大类+专业小类作为key
            String key = cleanMajorName + "|" + (classOne != null ? classOne : "") + "|" + (classTwo != null ? classTwo : "");

            MajorGroupInfo existing = mergedData.get(key);
            if (existing == null) {
                existing = new MajorGroupInfo();
                existing.setMajorName(cleanMajorName);
                existing.setClassOne(classOne);
                existing.setClassTwo(classTwo);
                existing.setTotalEnrollmentNumbers(0);
                existing.setSchoolCount(0);
                existing.setEnrollmentNumbers2024(0);
                existing.setEnrollmentNumbers2023(0);
                existing.setEnrollmentNumbers2022(0);
                existing.setSchoolCount2024(0);
                existing.setSchoolCount2023(0);
                existing.setSchoolCount2022(0);
                mergedData.put(key, existing);
            }

            // 累加数据
            existing.setTotalEnrollmentNumbers(existing.getTotalEnrollmentNumbers() + getIntegerValue(data, "totalEnrollmentNumbers"));
            existing.setSchoolCount(existing.getSchoolCount() + getIntegerValue(data, "schoolCount"));
            existing.setEnrollmentNumbers2024(existing.getEnrollmentNumbers2024() + getIntegerValue(data, "enrollmentNumbers2024"));
            existing.setSchoolCount2024(existing.getSchoolCount2024() + getIntegerValue(data, "schoolCount2024"));

            // 当查询特定年份时，不需要特殊处理，因为SQL已经将数据映射到标准字段
        }

        // 转换为列表并排序
        List<MajorGroupInfo> sortedList = mergedData.values().stream()
                .sorted((a, b) -> Integer.compare(b.getTotalEnrollmentNumbers(), a.getTotalEnrollmentNumbers()))
                .collect(Collectors.toList());

        // 手动分页
        int total = sortedList.size();
        int start = (reqVO.getPageNo() - 1) * reqVO.getPageSize();
        int end = Math.min(start + reqVO.getPageSize(), total);

        List<MajorGroupInfo> pageData = start < total ? sortedList.subList(start, end) : new ArrayList<>();

        return new PageResult<>(pageData, (long) total);
    }

    /**
     * 转换学校分组数据并关联学校基础信息
     */
    private List<SchoolGroupInfo> convertToSchoolGroupInfoWithCollegeInfo(List<Map<String, Object>> pageData) {
        if (pageData == null || pageData.isEmpty()) {
            return new ArrayList<>();
        }

        // 提取所有schoolUuid
        List<String> schoolUuids = pageData.stream()
                .map(data -> (String) data.get("school_uuid"))
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询学校基础信息
        Map<String, CollegeDO> collegeInfoMap = new HashMap<>();
        if (!schoolUuids.isEmpty()) {
            try {
                List<CollegeDO> collegeList = collegeService.getCollegeListBySchoolUuids(schoolUuids);
                collegeInfoMap = collegeList.stream()
                        .collect(Collectors.toMap(CollegeDO::getSchoolUuid, college -> college, (existing, replacement) -> existing));
            } catch (Exception e) {
                log.warn("批量查询学校基础信息失败: {}", e.getMessage(), e);
            }
        }

        // 转换数据并设置学校基础信息
        List<SchoolGroupInfo> schoolGroups = new ArrayList<>();
        for (Map<String, Object> data : pageData) {
            SchoolGroupInfo info = convertToSchoolGroupInfo(data);

            // 关联学校基础信息
            String schoolUuid = info.getSchoolUuid();
            if (schoolUuid != null && collegeInfoMap.containsKey(schoolUuid)) {
                CollegeDO collegeDO = collegeInfoMap.get(schoolUuid);
                setCollegeInfoToSchoolGroupInfo(info, collegeDO);
            }

            schoolGroups.add(info);
        }

        return schoolGroups;
    }

    /**
     * 转换学校分组数据
     */
    private SchoolGroupInfo convertToSchoolGroupInfo(Map<String, Object> data) {
        SchoolGroupInfo info = new SchoolGroupInfo();
        info.setSchoolUuid((String) data.get("school_uuid"));
        info.setSchoolName((String) data.get("school_name"));
        info.setTotalEnrollmentNumbers(getIntegerValue(data, "totalEnrollmentNumbers"));
        info.setMajorCount(getIntegerValue(data, "majorCount"));
        info.setEnrollmentNumbers2024(getIntegerValue(data, "enrollmentNumbers2024"));
        info.setEnrollmentNumbers2023(getIntegerValue(data, "enrollmentNumbers2023"));
        info.setEnrollmentNumbers2022(getIntegerValue(data, "enrollmentNumbers2022"));
        info.setMajorCount2024(getIntegerValue(data, "majorCount2024"));
        info.setMajorCount2023(getIntegerValue(data, "majorCount2023"));
        info.setMajorCount2022(getIntegerValue(data, "majorCount2022"));

        // 当查询特定年份时，不需要特殊处理，因为SQL已经将数据映射到标准字段

        return info;
    }

    /**
     * 处理专业分组的动态年份字段
     */
    private void handleDynamicYearFieldsForMajor(Map<String, Object> data, MajorGroupInfo info) {
        // 检查是否有当前年份的数据
        if (data.containsKey("currentYearEnrollmentNumbers") && data.containsKey("queryYear")) {
            int currentYearValue = getIntegerValue(data, "currentYearEnrollmentNumbers");
            int currentYearSchoolCount = getIntegerValue(data, "currentYearSchoolCount");
            int queryYear = getIntegerValue(data, "queryYear");

            // 根据查询年份累加到对应字段
            if (queryYear == 2024) {
                info.setEnrollmentNumbers2024(info.getEnrollmentNumbers2024() + currentYearValue);
                info.setSchoolCount2024(info.getSchoolCount2024() + currentYearSchoolCount);
            } else if (queryYear == 2023) {
                info.setEnrollmentNumbers2023(info.getEnrollmentNumbers2023() + currentYearValue);
                info.setSchoolCount2023(info.getSchoolCount2023() + currentYearSchoolCount);
            } else if (queryYear == 2022) {
                info.setEnrollmentNumbers2022(info.getEnrollmentNumbers2022() + currentYearValue);
                info.setSchoolCount2022(info.getSchoolCount2022() + currentYearSchoolCount);
            } else {
                // 对于其他年份（如2025），累加到2024字段中
                info.setEnrollmentNumbers2024(info.getEnrollmentNumbers2024() + currentYearValue);
                info.setSchoolCount2024(info.getSchoolCount2024() + currentYearSchoolCount);
            }
        }
    }

    /**
     * 处理动态年份字段
     */
    private void handleDynamicYearFields(Map<String, Object> data, SchoolGroupInfo info) {
        // 检查是否有当前年份的数据
        if (data.containsKey("currentYearEnrollmentNumbers") && data.containsKey("queryYear")) {
            int currentYearValue = getIntegerValue(data, "currentYearEnrollmentNumbers");
            int currentYearMajorCount = getIntegerValue(data, "currentYearMajorCount");
            int queryYear = getIntegerValue(data, "queryYear");

            // 根据查询年份设置到对应字段
            if (queryYear == 2024) {
                info.setEnrollmentNumbers2024(currentYearValue);
                info.setMajorCount2024(currentYearMajorCount);
            } else if (queryYear == 2023) {
                info.setEnrollmentNumbers2023(currentYearValue);
                info.setMajorCount2023(currentYearMajorCount);
            } else if (queryYear == 2022) {
                info.setEnrollmentNumbers2022(currentYearValue);
                info.setMajorCount2022(currentYearMajorCount);
            } else {
                // 对于其他年份（如2025），显示在2024字段中
                info.setEnrollmentNumbers2024(currentYearValue);
                info.setMajorCount2024(currentYearMajorCount);
            }
        }
    }

    /**
     * 设置学校基础信息到SchoolGroupInfo
     */
    private void setCollegeInfoToSchoolGroupInfo(SchoolGroupInfo schoolGroupInfo, CollegeDO collegeDO) {
        if (collegeDO == null) {
            return;
        }

        // 设置学校基础信息
        schoolGroupInfo.setProvince(collegeDO.getProvince());
        schoolGroupInfo.setCity(collegeDO.getCity());
        schoolGroupInfo.setDistrict(collegeDO.getDistrict());
        schoolGroupInfo.setCollegeType(collegeDO.getCollegeType());
        schoolGroupInfo.setIs985(collegeDO.getIs985());
        schoolGroupInfo.setIs211(collegeDO.getIs211());
        schoolGroupInfo.setIsDualClass(collegeDO.getIsDualClass());
        schoolGroupInfo.setCollegeCategory(collegeDO.getCollegeCategory());
        schoolGroupInfo.setCollegeTags(collegeDO.getCollegeTags());
        schoolGroupInfo.setEduLevel(collegeDO.getEduLevel());
        schoolGroupInfo.setCollegeProperty(collegeDO.getCollegeProperty());
        schoolGroupInfo.setCollegeCode(collegeDO.getCollegeCode());
        schoolGroupInfo.setRanking(collegeDO.getRanking());
        schoolGroupInfo.setRankingInCategory(collegeDO.getRankingInCategory());
        schoolGroupInfo.setWebsite(collegeDO.getWebsite());
        schoolGroupInfo.setCallNumber(collegeDO.getCallNumber());
        schoolGroupInfo.setEmail(collegeDO.getEmail());
        schoolGroupInfo.setAddress(collegeDO.getAddress());
        schoolGroupInfo.setCoverImage(collegeDO.getCoverImage());
        schoolGroupInfo.setIntro(collegeDO.getIntro());
        schoolGroupInfo.setExpenses(collegeDO.getExpenses());
        schoolGroupInfo.setOldName(collegeDO.getOldName());
        schoolGroupInfo.setShortName(collegeDO.getShortName());
    }

    /**
     * 转换专业分组数据
     */
    private MajorGroupInfo convertToMajorGroupInfo(Map<String, Object> data) {
        MajorGroupInfo info = new MajorGroupInfo();

        // 在Java层面处理专业名称，去除括号内容
        String rawMajorName = (String) data.get("majorName");
        String cleanMajorName = removeBracketsFromMajorName(rawMajorName);

        info.setMajorName(cleanMajorName);
        info.setClassOne((String) data.get("classOne"));
        info.setClassTwo((String) data.get("classTwo"));
        info.setTotalEnrollmentNumbers(getIntegerValue(data, "totalEnrollmentNumbers"));
        info.setSchoolCount(getIntegerValue(data, "schoolCount"));
        info.setEnrollmentNumbers2024(getIntegerValue(data, "enrollmentNumbers2024"));
        info.setEnrollmentNumbers2023(getIntegerValue(data, "enrollmentNumbers2023"));
        info.setEnrollmentNumbers2022(getIntegerValue(data, "enrollmentNumbers2022"));
        info.setSchoolCount2024(getIntegerValue(data, "schoolCount2024"));
        info.setSchoolCount2023(getIntegerValue(data, "schoolCount2023"));
        info.setSchoolCount2022(getIntegerValue(data, "schoolCount2022"));
        return info;
    }

    /**
     * 去除专业名称中的括号内容
     * 支持中文括号（）和英文括号()
     */
    private String removeBracketsFromMajorName(String majorName) {
        if (majorName == null || majorName.trim().isEmpty()) {
            return majorName;
        }

        // 同时检查英文括号和中文括号
        int englishBracketIndex = majorName.indexOf('(');
        int chineseBracketIndex = majorName.indexOf('（');

        int bracketIndex = -1;
        if (englishBracketIndex > 0 && chineseBracketIndex > 0) {
            // 如果两种括号都存在，选择最早出现的
            bracketIndex = Math.min(englishBracketIndex, chineseBracketIndex);
        } else if (englishBracketIndex > 0) {
            bracketIndex = englishBracketIndex;
        } else if (chineseBracketIndex > 0) {
            bracketIndex = chineseBracketIndex;
        }

        if (bracketIndex > 0) {
            return majorName.substring(0, bracketIndex).trim();
        }

        return majorName;
    }

    /**
     * 提取专业名称中括号内的所有专业名称
     * 支持中文括号（）和英文括号()
     * 例如：计算机类(计算机科学与技术、软件工程) -> [计算机科学与技术, 软件工程]
     * @param majorName 包含括号的专业名称
     * @return 括号内的专业名称列表
     */
    private List<String> extractMajorNamesFromBrackets(String majorName) {
        List<String> result = new ArrayList<>();

        if (majorName == null || majorName.trim().isEmpty()) {
            return result;
        }

        // 同时支持中文括号（）和英文括号()
        int startIndex = -1;
        int endIndex = -1;

        // 查找英文括号
        int englishStart = majorName.indexOf('(');
        int englishEnd = majorName.lastIndexOf(')');

        // 查找中文括号
        int chineseStart = majorName.indexOf('（');
        int chineseEnd = majorName.lastIndexOf('）');

        // 选择最早出现的开始括号
        if (englishStart > 0 && chineseStart > 0) {
            startIndex = Math.min(englishStart, chineseStart);
        } else if (englishStart > 0) {
            startIndex = englishStart;
        } else if (chineseStart > 0) {
            startIndex = chineseStart;
        }

        // 选择对应的结束括号
        if (startIndex == englishStart && englishEnd > startIndex) {
            endIndex = englishEnd;
        } else if (startIndex == chineseStart && chineseEnd > startIndex) {
            endIndex = chineseEnd;
        }

        if (startIndex > 0 && endIndex > startIndex) {
            String bracketContent = majorName.substring(startIndex + 1, endIndex);

            // 按照中文顿号、逗号等分隔符分割
            String[] parts = bracketContent.split("[、，,]");

            for (String part : parts) {
                String trimmed = part.trim();
                if (!trimmed.isEmpty()) {
                    result.add(trimmed);
                }
            }
        }

        return result;
    }

    /**
     * 扩展专业名称列表，包含原始名称和括号内的专业名称
     * @param majorNames 原始专业名称列表
     * @return 扩展后的专业名称列表
     */
    private List<String> expandMajorNamesWithBracketContent(List<String> majorNames) {
        Set<String> expandedNames = new HashSet<>();

        for (String majorName : majorNames) {
            // 添加去除括号后的名称
            String cleanName = removeBracketsFromMajorName(majorName);
            if (!cleanName.isEmpty()) {
                expandedNames.add(cleanName);
            }

            // 添加括号内的专业名称
            List<String> bracketNames = extractMajorNamesFromBrackets(majorName);
            expandedNames.addAll(bracketNames);
        }

        return new ArrayList<>(expandedNames);
    }

    /**
     * 检查两个专业名称是否匹配（支持括号内容匹配）
     * @param majorName1 专业名称1
     * @param majorName2 专业名称2
     * @return 是否匹配
     */
    private boolean isMajorNameMatch(String majorName1, String majorName2) {
        if (majorName1 == null || majorName2 == null) {
            return false;
        }

        // 1. 直接匹配
        if (majorName1.equals(majorName2)) {
            return true;
        }

        // 2. 去除括号后匹配
        String clean1 = removeBracketsFromMajorName(majorName1);
        String clean2 = removeBracketsFromMajorName(majorName2);
        if (clean1.equals(clean2)) {
            return true;
        }

        // 3. 检查是否有一个专业名称在另一个的括号内
        List<String> brackets1 = extractMajorNamesFromBrackets(majorName1);
        List<String> brackets2 = extractMajorNamesFromBrackets(majorName2);

        // 检查 majorName2 的去括号名称是否在 majorName1 的括号内
        if (brackets1.contains(clean2)) {
            return true;
        }

        // 检查 majorName1 的去括号名称是否在 majorName2 的括号内
        if (brackets2.contains(clean1)) {
            return true;
        }

        // 4. 检查括号内的专业名称是否有交集
        for (String bracket1 : brackets1) {
            if (brackets2.contains(bracket1)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 检查数据库中各年份的数据可用性
     * @param provinceName 省份名称
     */
    private void checkYearlyDataAvailability(String provinceName) {
        try {
            List<Integer> years = Arrays.asList(2025, 2024, 2023, 2022);
            log.info("检查数据库中各年份招生计划数据情况：");

            for (Integer year : years) {
                Long count = collegeEnrollmentPlanMapper.countByYear(year);
                log.info("  {}年：总共{}条记录", year, count);

                if (provinceName != null) {
                    Long provinceCount = collegeEnrollmentPlanMapper.countByYearAndProvince(year, provinceName);
                    log.info("  {}年{}省：{}条记录", year, provinceName, provinceCount);
                }
            }
        } catch (Exception e) {
            log.warn("检查年份数据可用性失败: {}", e.getMessage());
        }
    }

    /**
     * 安全获取Integer值
     */
    private Integer getIntegerValue(Map<String, Object> data, String key) {
        Object value = data.get(key);
        if (value == null) {
            return 0;
        }
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        try {
            return Integer.parseInt(value.toString());
        } catch (NumberFormatException e) {
            log.warn("无法转换值为Integer: key={}, value={}", key, value);
            return 0;
        }
    }

    /**
     * 安全将招生人数字符串转换为Integer值
     * 处理横杠"-"等特殊情况
     */
    private Integer parseEnrollmentNumbers(String enrollmentNumbers) {
        if (enrollmentNumbers == null || enrollmentNumbers.trim().isEmpty()) {
            return 0;
        }

        String trimmed = enrollmentNumbers.trim();

        // 如果是横杠或其他非数字字符，返回0
        if ("-".equals(trimmed) || "—".equals(trimmed) || "无".equals(trimmed) || "不限".equals(trimmed)) {
            return 0;
        }

        try {
            return Integer.parseInt(trimmed);
        } catch (NumberFormatException e) {
            log.warn("无法转换招生人数为Integer: value={}", enrollmentNumbers);
            return 0;
        }
    }

    /**
     * 转换CollegeEnrollmentPlanDO为CollegeEnrollmentPlanInfo
     * @param planDO 数据库实体对象
     * @return API返回格式的数据对象
     */
    private CollegeEnrollmentPlanInfo convertToCollegeEnrollmentPlanInfo(CollegeEnrollmentPlanDO planDO) {
        if (planDO == null) {
            return null;
        }

        CollegeEnrollmentPlanInfo planInfo = new CollegeEnrollmentPlanInfo();

        // 基本字段映射
        planInfo.setProvinceName(planDO.getProvinceName());
        planInfo.setSchoolUuid(planDO.getSchoolUuid());
        planInfo.setSchoolName(planDO.getSchoolName());
        planInfo.setCollegeMajorName(planDO.getCollegeMajorName());
        planInfo.setCollegeMajorCode(planDO.getCollegeMajorCode());
        planInfo.setYear(planDO.getYear());
        planInfo.setEnrollmentNumbers(planDO.getEnrollmentNumbers());
        planInfo.setInSchoolYears(planDO.getInSchoolYears());
        planInfo.setClassOne(planDO.getClassOne());
        planInfo.setClassTwo(planDO.getClassTwo());
        planInfo.setBatchName(planDO.getBatchName());
        planInfo.setType(planDO.getType());
        planInfo.setCourseSelectionRequirements(planDO.getCourseSelectionRequirements());
        planInfo.setSpecialGroup(planDO.getSpecialGroup());
        planInfo.setSpecialCode(planDO.getSpecialCode());
        planInfo.setSpecialGroupName(planDO.getSpecialGroupName());
        planInfo.setCollegeMajorBracketContent(planDO.getCollegeMajorBracketContent());

        return planInfo;
    }

    /**
     * 构建唯一标识键，用于去重
     * @param plan 招生计划对象
     * @return 唯一标识字符串
     */
    private String buildUniqueKey(CollegeEnrollmentPlanDO plan) {
        // 使用StringBuilder构建唯一标识，性能更好
        StringBuilder keyBuilder = new StringBuilder(128); // 预分配容量
        return keyBuilder
                .append(plan.getYear()).append(':')
                .append(plan.getSchoolName() != null ? plan.getSchoolName() : "").append(':')
                .append(plan.getCollegeMajorName() != null ? plan.getCollegeMajorName() : "").append(':')
                .append(plan.getBatchName() != null ? plan.getBatchName() : "").append(':')
                .append(plan.getType() != null ? plan.getType() : "").append(':')
                .append(plan.getProvinceName() != null ? plan.getProvinceName() : "")
                .toString();
    }

    @Override
    public Map<String, Object> batchProcessMajorNameBracketContent(int batchSize, int threadCount) {
        log.info("开始批量处理专业名称括号内容，批次大小: {}, 线程数: {}", batchSize, threadCount);

        Map<String, Object> result = new HashMap<>();
        long startTime = System.currentTimeMillis();

        try {
            // 1. 统计需要处理的数据量
            long totalRecords = collegeEnrollmentPlanMapper.selectCount(null);
            LambdaQueryWrapper<CollegeEnrollmentPlanDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.and(w -> w.like(CollegeEnrollmentPlanDO::getCollegeMajorName, "（")
                             .or().like(CollegeEnrollmentPlanDO::getCollegeMajorName, "("));
            long recordsWithBrackets = collegeEnrollmentPlanMapper.selectCount(wrapper);

            log.info("数据统计 - 总记录数: {}, 包含括号的记录数: {}", totalRecords, recordsWithBrackets);

            if (recordsWithBrackets == 0) {
                result.put("success", true);
                result.put("message", "没有需要处理的数据");
                result.put("totalRecords", totalRecords);
                result.put("processedRecords", 0);
                return result;
            }

            // 2. 分批处理数据
            AtomicInteger processedCount = new AtomicInteger(0);
            AtomicInteger updatedCount = new AtomicInteger(0);

            // 创建线程池
            ExecutorService executor = Executors.newFixedThreadPool(threadCount);
            List<CompletableFuture<Void>> futures = new ArrayList<>();

            // 计算总批次数
            int totalBatches = (int) Math.ceil((double) recordsWithBrackets / batchSize);
            log.info("预计需要处理 {} 个批次", totalBatches);

            for (int batch = 0; batch < totalBatches; batch++) {
                final int currentBatch = batch;
                final int offset = batch * batchSize;

                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        processBatchMajorNameBracketContent(offset, batchSize, processedCount, updatedCount, currentBatch + 1, totalBatches);
                    } catch (Exception e) {
                        log.error("处理第{}批数据时发生异常", currentBatch + 1, e);
                    }
                }, executor);

                futures.add(future);
            }

            // 等待所有任务完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
            executor.shutdown();

            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            result.put("success", true);
            result.put("message", "批量处理完成");
            result.put("totalRecords", totalRecords);
            result.put("recordsWithBrackets", recordsWithBrackets);
            result.put("processedRecords", processedCount.get());
            result.put("updatedRecords", updatedCount.get());
            result.put("duration", duration);
            result.put("durationFormatted", formatDuration(duration));

            log.info("批量处理完成 - 处理记录数: {}, 更新记录数: {}, 耗时: {}ms",
                    processedCount.get(), updatedCount.get(), duration);

        } catch (Exception e) {
            log.error("批量处理专业名称括号内容失败", e);
            result.put("success", false);
            result.put("message", "处理失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 处理单个批次的专业名称括号内容
     */
    private void processBatchMajorNameBracketContent(int offset, int batchSize,
                                                   AtomicInteger processedCount, AtomicInteger updatedCount,
                                                   int currentBatch, int totalBatches) {
        try {
            // 查询包含括号的数据
            LambdaQueryWrapper<CollegeEnrollmentPlanDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.and(w -> w.like(CollegeEnrollmentPlanDO::getCollegeMajorName, "（")
                                  .or().like(CollegeEnrollmentPlanDO::getCollegeMajorName, "("))
                        .last("LIMIT " + offset + ", " + batchSize);
            List<CollegeEnrollmentPlanDO> records = collegeEnrollmentPlanMapper.selectList(queryWrapper);

            if (records.isEmpty()) {
                log.debug("第{}批没有找到需要处理的数据", currentBatch);
                return;
            }

            int batchUpdated = 0;

            for (CollegeEnrollmentPlanDO record : records) {
                try {
                    String originalName = record.getCollegeMajorName();
                    if (originalName == null || originalName.trim().isEmpty()) {
                        continue;
                    }

                    // 使用工具类处理专业名称
                    MajorNameBracketProcessor.MajorNameProcessResult processResult =
                        MajorNameBracketProcessor.processMajorName(originalName);

                    // 如果有括号内容，则更新记录
                    if (processResult.hasBracketContent()) {
                        record.setCollegeMajorName(processResult.getCleanMajorName());
                        record.setCollegeMajorBracketContent(processResult.getBracketContent());

                        collegeEnrollmentPlanMapper.updateById(record);
                        batchUpdated++;

                        if (log.isDebugEnabled()) {
                            log.debug("更新记录 ID: {}, 原名称: {}, 新名称: {}, 括号内容: {}",
                                    record.getId(), originalName, processResult.getCleanMajorName(),
                                    processResult.getBracketContent());
                        }
                    }

                } catch (Exception e) {
                    log.error("处理记录 ID: {} 时发生异常", record.getId(), e);
                }
            }

            processedCount.addAndGet(records.size());
            updatedCount.addAndGet(batchUpdated);

            log.info("完成第{}/{}批处理，本批处理{}条记录，更新{}条记录，累计处理{}条",
                    currentBatch, totalBatches, records.size(), batchUpdated, processedCount.get());

        } catch (Exception e) {
            log.error("处理第{}批数据时发生异常", currentBatch, e);
        }
    }

    /**
     * 格式化持续时间
     */
    private String formatDuration(long milliseconds) {
        long seconds = milliseconds / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        
        if (hours > 0) {
            return String.format("%d小时%d分钟%d秒", hours, minutes % 60, seconds % 60);
        } else if (minutes > 0) {
            return String.format("%d分钟%d秒", minutes, seconds % 60);
        } else {
            return String.format("%d秒", seconds);
        }
    }
    
    /**
     * 从专业名称中提取专业组信息用于智能匹配
     * 支持多种格式：1093（W003）、（W003）、（003）等
     * @param majorName 专业名称
     * @return 提取的专业组信息，如果没有则返回null
     */
    private String extractSubjectGroupFromMajorName(String majorName) {
        if (majorName == null || majorName.trim().isEmpty()) {
            return null;
        }
        
        String trimmed = majorName.trim();
        
        // 1. 提取中文括号内的内容：（003）或（W003）
        java.util.regex.Pattern chineseParenPattern = java.util.regex.Pattern.compile("（([^）]+)）");
        java.util.regex.Matcher chineseMatcher = chineseParenPattern.matcher(trimmed);
        if (chineseMatcher.find()) {
            String content = chineseMatcher.group(1);
            log.debug("从专业名称 {} 中提取中文括号内容: {}", majorName, content);
            return content;
        }
        
        // 2. 提取英文括号内的内容：(003)或(W003)
        java.util.regex.Pattern englishParenPattern = java.util.regex.Pattern.compile("\\(([^)]+)\\)");
        java.util.regex.Matcher englishMatcher = englishParenPattern.matcher(trimmed);
        if (englishMatcher.find()) {
            String content = englishMatcher.group(1);
            log.debug("从专业名称 {} 中提取英文括号内容: {}", majorName, content);
            return content;
        }
        
        // 3. 提取数字+括号格式：1093（W003）中的W003
        java.util.regex.Pattern numberParenPattern = java.util.regex.Pattern.compile("\\d+[（(]([^）)]+)[）)]");
        java.util.regex.Matcher numberMatcher = numberParenPattern.matcher(trimmed);
        if (numberMatcher.find()) {
            String content = numberMatcher.group(1);
            log.debug("从专业名称 {} 中提取数字+括号内容: {}", majorName, content);
            return content;
        }
        
        log.debug("从专业名称 {} 中未找到专业组信息", majorName);
        return null;
    }
}
